import sys
import io
import subprocess
import argparse
from datetime import datetime

sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')

def run_git_command(cmd):
    try:
        result = subprocess.check_output(cmd, shell=True, text=True,
                                         encoding='utf-8', errors='replace',
                                         stderr=subprocess.STDOUT)
        return result.strip()
    except subprocess.CalledProcessError as e:
        print(f"Error executing command: {cmd}\n{e.output}")
        return None

def get_commits(start_date, end_date):
    since = f"{start_date} 00:00:00"
    until = f"{end_date} 23:59:59"
    cmd = f'git log master --since="{since}" --until="{until}" --date=iso --pretty=format:"%H|%an|%ai|%P|%s"'
    output = run_git_command(cmd)
    commits = []
    commit_ids = set()
    exclude_commits = set()

    if output:
        for line in output.split('\n'):
            if not line.strip():
                continue
            try:
                commit_id, author, date_str, parents, message = line.split('|', 4)
            except ValueError:
                continue
            if commit_id in commit_ids:
                continue
            is_merge = ' ' in parents
            if is_merge:
                exclude_commits.add(commit_id)
                parents_list = parents.split()
                if len(parents_list) >= 2:
                    p1 = parents_list[0]
                    p2 = parents_list[1]
                    # 修复命令：添加 --no-merges
                    new_commits_cmd = f'git log {p1}..{p2} --no-merges --pretty=format:"%H|%an|%ai|%P|%s"'
                    new_commits_output = run_git_command(new_commits_cmd)
                    if new_commits_output:
                        for new_line in new_commits_output.split('\n'):
                            if not new_line.strip():
                                continue
                            try:
                                new_commit_id, new_author, new_date_str, new_parents, new_message = new_line.split('|', 4)
                            except ValueError:
                                continue
                            # 修复去重逻辑
                            if new_commit_id not in commit_ids:
                                is_new_merge = ' ' in new_parents
                                if is_new_merge:
                                    exclude_commits.add(new_commit_id)
                                commits.append((new_commit_id, new_author, new_date_str, new_parents.strip(), is_new_merge, new_message))
                                commit_ids.add(new_commit_id)
            else:
                commits.append((commit_id, author, date_str, parents.strip(), is_merge, message))
                commit_ids.add(commit_id)

    filtered_commits = [c for c in commits if c[0] not in exclude_commits]
    return filtered_commits

def get_changes_stats(commit_id):
    cmd = f"git show --numstat {commit_id}"
    output = run_git_command(cmd)
    if not output:
        return (0, 0)
    adds, dels = 0, 0
    for line in output.split('\n'):
        if not line or line.startswith(' '):
            continue
        parts = line.split()
        if len(parts) >= 2:
            try:
                add = int(parts[0]) if parts[0].isdigit() else 0
                dele = int(parts[1]) if parts[1].isdigit() else 0
                adds += add
                dels += dele
            except ValueError:
                pass
    return (adds, dels)

def main():
    parser = argparse.ArgumentParser(description="Analyze Git commits within a specific date range")
    parser.add_argument("--start-date", type=str, required=True, help="Start date in YYYY-MM-DD format")
    parser.add_argument("--end-date", type=str, required=True, help="End date in YYYY-MM-DD format")
    args = parser.parse_args()

    try:
        datetime.strptime(args.start_date, "%Y-%m-%d")
        datetime.strptime(args.end_date, "%Y-%m-%d")
    except ValueError:
        print("Invalid date format. Use YYYY-MM-DD.")
        return

    commits = get_commits(args.start_date, args.end_date)
    if not commits:
        print(f"No commits found between {args.start_date} and {args.end_date}")
        return

    print(f"Commits between {args.start_date} and {args.end_date} (excluding all merge commits):")
    for commit in commits:
        commit_id, author, date_str, parents, is_merge, message = commit
        adds, dels = get_changes_stats(commit_id)
        clean_message = message.replace('\n', ' ').strip()
        print(f"Commit: {commit_id} | Author: {author} | Date: {date_str} | Message: {clean_message} | Changes(+/-): {adds},{dels}")

    print(f"Commits between {args.start_date} and {args.end_date} (excluding merge commits):")
    author_stats = {}  # 按作者存储总变更量

    for commit in commits:
        commit_id, author, date_str, parents, is_merge, message = commit
        adds, dels = get_changes_stats(commit_id)
        total = adds + dels

        # 更新作者统计
        if author not in author_stats:
            author_stats[author] = {'adds': 0, 'dels': 0, 'total': 0}
        author_stats[author]['adds'] += adds
        author_stats[author]['dels'] += dels
        author_stats[author]['total'] += total

        # 打印单条提交记录
        clean_message = message.replace('\n', ' ').strip()
        print(f"Commit: {commit_id} | Author: {author} | Changes(+/-): {adds},{dels} | Message: {clean_message}")

    # 打印作者总统计
    print("\nTotal changes per author:")
    for author, stats in author_stats.items():
        print(f"Author: {author} | Adds: {stats['adds']} | Dels: {stats['dels']} | Total: {stats['total']}")


if __name__ == "__main__":
    main()